package com.platform.metamodel.service.impl;

import com.platform.metamodel.service.JdbcUpdateService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.metamodel.create.CreateIndex;
import org.apache.metamodel.create.CreateTable;
import org.apache.metamodel.drop.DropIndex;
import org.apache.metamodel.drop.DropTable;
import org.apache.metamodel.jdbc.JdbcDataContext;
import org.apache.metamodel.jdbc.JdbcQueryIndex;
import org.apache.metamodel.jdbc.JdbcQueryUniqueKeys;
import org.apache.metamodel.modify.ActionType;
import org.apache.metamodel.modify.ModifyTable;
import org.apache.metamodel.schema.MutableColumn;
import org.apache.metamodel.schema.MutableIndex;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.schema.UniqueKeys;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author liujizheng
 * @version 1.0
 * @ClassName JdbcUpdateServiceImpl
 * @Description jdbc 表操作
 * @date 2021/8/9 11:56
 */
@Component
public class JdbcUpdateServiceImpl implements JdbcUpdateService {
    public static ThreadLocal<Map<String,String>> localVar = new ThreadLocal<Map<String,String>>();
    /**
     * 创建表
     *
     * @param dataSource  数据源
     * @param createTable 创建表封装
     * @return 执行成功： true
     */
    @Override
    public boolean createTable(DataSource dataSource, CreateTable createTable) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(createTable);
        return true;
    }

    @Override
    public boolean dropTable(DataSource dataSource, String schemaName, String tableName){
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(new DropTable(schemaName,tableName));
        return true;
    }

    /**
     * 创建表
     *
     * @param connection  数据库连接
     * @param createTable 创建表封装
     * @return 执行成功： true
     */
    @Override
    public boolean createTable(Connection connection, CreateTable createTable) {
        JdbcDataContext context = new JdbcDataContext(connection);
        context.executeUpdate(createTable);
        return true;
    }



    /**
     * 创建表
     *
     * @param dataSource 数据源
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param columnList 字段列表
     * @return 执行成功： true
     */
    @Override
    public boolean createTable(DataSource dataSource, String schemaName, String tableName, List<MutableColumn> columnList,Map<String,String> map) {
        if(null != map){
            localVar.set(map);
        }
        return createTable(dataSource, new CreateTable(schemaName, tableName, columnList));
    }
    @Override
    public boolean createTable(DataSource dataSource, String schemaName, String tableName, List<MutableColumn> columnList) {
        return createTable(dataSource, new CreateTable(schemaName, tableName, columnList));
    }
    /**
     * 创建表
     *
     * @param connection 数据库连接
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param columnList 字段列表
     * @return 执行成功： true
     */
    @Override
    public boolean createTable(Connection connection, String schemaName, String tableName, List<MutableColumn> columnList) {
        return createTable(connection, new CreateTable(schemaName, tableName, columnList));
    }

    /**
     * 表增加字段
     *
     * @param dataSource 数据源
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param column     字段
     * @return 执行成功： true
     */
    @Override
    public boolean addColumn(DataSource dataSource, String schemaName, String tableName, MutableColumn column) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(ModifyTable.addColumn(context, schemaName, tableName, column));
        return true;
    }

    /**
     * 表增加字段
     *
     * @param connection 数据库连接
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param column     字段
     * @return 执行成功： true
     */
    @Override
    public boolean addColumn(Connection connection, String schemaName, String tableName, MutableColumn column) {
        JdbcDataContext context = new JdbcDataContext(connection);
        context.executeUpdate(ModifyTable.addColumn(context, schemaName, tableName, column));
        return true;
    }

    /**
     * 表删除字段
     *
     * @param dataSource 数据源
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param columnName 字段名
     * @return 执行成功： true
     */
    @Override
    public boolean dropColumn(DataSource dataSource, String schemaName, String tableName, String columnName) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(ModifyTable.dropColumn(context, schemaName, tableName, columnName));
        return true;
    }

    /**
     * 表删除字段
     *
     * @param connection 数据库连接
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param columnName 字段名
     * @return 执行成功： true
     */
    @Override
    public boolean dropColumn(Connection connection, String schemaName, String tableName, String columnName) {
        JdbcDataContext context = new JdbcDataContext(connection);
        context.executeUpdate(ModifyTable.dropColumn(context, schemaName, tableName, columnName));
        return true;
    }

    /**
     * 表修改字段
     *
     * @param dataSource 数据源
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param column     字段
     * @return 执行成功： true
     */
    @Override
    public boolean modifyColumn(DataSource dataSource, String schemaName, String tableName, MutableColumn column) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(ModifyTable.modifyColumn(context, schemaName, tableName, column));
        return true;
    }

    /**
     * 表修改字段
     *
     * @param connection 数据库连接
     * @param schemaName 方案或数据库名
     * @param tableName  数据表名
     * @param column     字段
     * @return 执行成功： true
     */
    @Override
    public boolean modifyColumn(Connection connection, String schemaName, String tableName, MutableColumn column) {
        JdbcDataContext context = new JdbcDataContext(connection);
        context.executeUpdate(ModifyTable.modifyColumn(context, schemaName, tableName, column));
        return true;
    }

    @Override
    public boolean existsTable(DataSource dataSource, String schemaName, String tableName) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        return context.getSchemaByName(schemaName).getTableByName(tableName) != null;
    }

    @Override
    public Table getTableDDL(DataSource dataSource, String schemaName, String tableName) {
        Assert.isTrue(StringUtils.isNotEmpty(schemaName),"schemaName不能为空");
        JdbcDataContext context = new JdbcDataContext(dataSource);
        return context.getSchemaByName(schemaName).getTableByName(tableName);
    }

    @Override
    public List<String> getTableNames(DataSource dataSource, String schemaName) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        return context.getSchemaByName(schemaName).getTableNames();
    }

    @Override
    public boolean createIndex(DataSource dataSource, CreateIndex createIndex) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(createIndex);
        return true;
    }

    @Override
    public boolean dropIndex(DataSource dataSource, DropIndex dropIndex) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(dropIndex);
        return true;
    }

    @Override
    public boolean addFKConstraint(DataSource dataSource,
                                   String fkName,
                                   String slaveSchemaName,
                                   String slaveTableName,
                                   List<MutableColumn> slaveColumns,
                                   String masterSchemaName,
                                   String masterTableName,
                                   List<MutableColumn> masterColumns,
                                   ActionType deleteAction,
                                   ActionType updateAction) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(ModifyTable.addFKConstraint(context,
                fkName,
                slaveSchemaName,
                slaveTableName,
                slaveColumns,
                masterSchemaName,
                masterTableName,
                masterColumns,
                deleteAction,
                updateAction));
        return true;
    }

    @Override
    public boolean dropFKConstraint(DataSource dataSource,
                                    String fkName,
                                    String slaveSchemaName,
                                    String slaveTableName) {
        JdbcDataContext context = new JdbcDataContext(dataSource);
        context.executeUpdate(ModifyTable.dropFKConstraint(context,fkName,slaveSchemaName,slaveTableName));
        return true;
    }

    @Override
    public List<MutableIndex> findIndexs(DataSource dataSource, String schemaName, String tableName) {
        JdbcQueryIndex jdbcQueryIndex = new JdbcQueryIndex(dataSource);
        List<MutableIndex> indexList = jdbcQueryIndex.getIndexBySchemaAndTable(schemaName,tableName);
        if(CollectionUtils.isNotEmpty(indexList)){
            indexList.forEach(idx -> {
                if(CollectionUtils.isNotEmpty(idx.getColumns())){
                    idx.getColumns().forEach(col -> {
                        ((MutableColumn)col).setTable(null);
                    });
                }
            });
        }
        return indexList;
    }

    @Override
    public List<UniqueKeys> findUniqueKeys(DataSource dataSource, String catalog, String schemaName, String tableName) {
        JdbcQueryUniqueKeys jdbcQueryUniqueKeys = new JdbcQueryUniqueKeys(dataSource);
        List<UniqueKeys> uniqueKeys = jdbcQueryUniqueKeys.getUniqueKeysBySchemaAndTable(catalog,schemaName,tableName);
        if(CollectionUtils.isEmpty(uniqueKeys)){
            return new ArrayList<>();
        }
        return uniqueKeys;
    }

}
